#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
    #include "wx/mdi.h"
#endif

#include "wx/toolbar.h"
#include "wx/grid.h"
#include "wx/dialog.h"
#include "wx/spinctrl.h"
#include "wx/stattext.h"
#include "wx/textdlg.h"

#include <sqlite3.h>
#include <sqlite3util.h>
#include "dbi.h"
#include "mdi.h"
#include <Configuration.h>

//linux header include
#include <sys/types.h>
#include <signal.h>
#include <iostream>
#include <vector>

extern ConfigurationTable gConfig;
extern MainFrame *gPtrframe;
extern wxList my_children;
//IMSI list was saved in TMSITable, short number was saved in sip_buddies
extern IMSITable gIMSITable;
extern SingleColDBI gSIPBuddies;
extern int gs_nFrames;
extern void startSipProcess();
extern void startSmqProcess();
extern void startBtsProcess();


// ---------------------------------------------------------------------------
// GsmModalDialog
// ---------------------------------------------------------------------------
BEGIN_EVENT_TABLE(GsmModalDialog, wxDialog)
    EVT_BUTTON(wxID_ANY, GsmModalDialog::OnButton)
END_EVENT_TABLE()
GsmModalDialog::GsmModalDialog(wxWindow *parent)
    :wxDialog(parent, 
        wxID_ANY, wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
    wxBoxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *sizerButtom = new wxBoxSizer(wxHORIZONTAL);
    wxGridSizer *gridSizer = new wxGridSizer(8, 2, 0, 0);
    wxStaticText * label = new wxStaticText(
        this, 
        wxID_STATIC, 
        _("MCC value:"), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxALIGN_LEFT);
        
    gridSizer->Add(
        label,
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 
        5);
    m_spinMCC = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(" "), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinMCC,
        1, 
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL, 
        5);
    gridSizer->Add(
        new wxStaticText(
            this, 
            wxID_STATIC, 
            _("MNC value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL |wxALL,
        5);
    m_spinMNC = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(" "), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinMNC,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    gridSizer->Add(
        new wxStaticText(
            this, 
            wxID_STATIC, 
            _("LAC value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_spinLAC = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(" "), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinLAC,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    gridSizer->Add(
        new wxStaticText(
            this, 
            wxID_STATIC, 
            _("CellID value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_spinCellID = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinCellID,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    gridSizer->Add(
        new wxStaticText(
            this, 
            wxID_STATIC, 
            _("NCC value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_spinNCC = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinNCC,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    gridSizer->Add(
        new wxStaticText(
            this,
            wxID_STATIC, 
            _("BCC value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_spinBCC = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinBCC,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    gridSizer->Add(
        new wxStaticText(
            this, 
            wxID_STATIC, 
            _("Arfcn value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_spinArfcn = new wxTextCtrl(
        this, 
        wxID_ANY, 
        wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinArfcn,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    gridSizer->Add(
        new wxStaticText(
            this, 
            wxID_STATIC, 
            _("Neighbor Cell value: "), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT),
        0,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_spinNeighborCell = new wxTextCtrl(
        this, 
        wxID_ANY, wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT);
    gridSizer->Add(
        m_spinNeighborCell,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);

    m_btnOK = new wxButton(this, wxID_ANY, _("OK"));
    m_btnReboot = new wxButton(this, wxID_ANY, _("Reboot"));
    m_btnApply = new wxButton(this, wxID_ANY, _("Apply"));
    m_btnCancel = new wxButton(this, wxID_ANY, _("Cancel"));
    m_btnMail = new wxButton(this, wxID_ANY, _("Set Mail"));
    sizerButtom->Add(m_btnOK, 0, wxALIGN_CENTER | wxALL, 5);
    sizerButtom->Add(m_btnReboot, 0, wxALIGN_CENTER | wxALL, 5);
    sizerButtom->Add(m_btnApply, 0, wxALIGN_CENTER | wxALL, 5);
    sizerButtom->Add(m_btnCancel, 0, wxALIGN_CENTER | wxALL, 5);
    sizerButtom->Add(m_btnMail, 0, wxALIGN_CENTER | wxALL, 5);
    sizerTop->Add(gridSizer, 1, wxALIGN_CENTER);
    sizerTop->Add(sizerButtom, 0, wxALIGN_CENTER);
    SetSizer(sizerTop);
    sizerTop->Fit(this);
    sizerTop->SetSizeHints(this);

    //set config value to spin control
    update();
}

void GsmModalDialog::update()
{
    wxString strMCC(gConfig.getStr("GSM.Identity.MCC").c_str(), wxConvUTF8);
    m_spinMCC->SetValue(strMCC);

    wxString strMNC(gConfig.getStr("GSM.Identity.MNC").c_str(), wxConvUTF8);
    m_spinMNC->SetValue(strMNC);

    wxString strLAC(gConfig.getStr("GSM.Identity.LAC").c_str(), wxConvUTF8);
    m_spinLAC->SetValue(strLAC);

    wxString strCELL_ID(gConfig.getStr("GSM.Identity.CI").c_str(), wxConvUTF8);
    m_spinCellID->SetValue(strCELL_ID);

    wxString strNeighborCell(gConfig.getStr("GSM.CellSelection.Neighbors").c_str(), wxConvUTF8);
    m_spinNeighborCell->SetValue(strNeighborCell);

    wxString strArfcn(gConfig.getStr("GSM.Radio.C0").c_str(), wxConvUTF8);
    m_spinArfcn->SetValue(strArfcn);

    wxString strNCC(gConfig.getStr("GSM.Identity.BSIC.NCC").c_str(), wxConvUTF8);
    m_spinNCC->SetValue(strNCC);

    wxString strBCC(gConfig.getStr("GSM.Identity.BSIC.BCC").c_str(), wxConvUTF8);
    m_spinBCC->SetValue(strBCC);    
}

void GsmModalDialog::apply()
{
    //save all config to DB
    gConfig.set("GSM.Identity.MCC", std::string(m_spinMCC->GetValue().mb_str()));
    gConfig.set("GSM.Identity.MNC", std::string(m_spinMNC->GetValue().mb_str()));
    gConfig.set("GSM.Identity.CI", std::string(m_spinCellID->GetValue().mb_str()));
    gConfig.set("GSM.Identity.LAC", std::string(m_spinLAC->GetValue().mb_str()));
    gConfig.set("GSM.CellSelection.Neighbors", std::string(m_spinNeighborCell->GetValue().mb_str()));
    gConfig.set("GSM.Radio.C0", std::string(m_spinArfcn->GetValue().mb_str()));
    gConfig.set("GSM.Identity.BSIC.NCC", std::string(m_spinNCC->GetValue().mb_str()));
    gConfig.set("GSM.Identity.BSIC.BCC", std::string(m_spinBCC->GetValue().mb_str()));
}

void GsmModalDialog::setMail()
{
    std::string strVal = gConfig.getStr("Admin.mail");
    wxString wxStrVal(strVal.c_str(), wxConvUTF8);
    wxString strAddress = ::wxGetTextFromUser(
        _("Mail Address"), 
        _("Please Set Mail"),
        wxStrVal, 
        this,
        wxDefaultCoord,
        wxDefaultCoord,
        false);
    std::string strAddrVal(strAddress.mb_str());
    gConfig.set("Admin.mail", strAddrVal);
}

void GsmModalDialog::OnButton(wxCommandEvent& evt)
{
    if (evt.GetEventObject() == m_btnReboot)
    {
        //TODO: here is the place to write reboot code
        //gBTS.GSMConfig();    
        //gBtsConfig.set("Sys.Reboot", "1");
        m_btnReboot->Enable(false);
        system("./rc.bts stop");
        startSipProcess();
        startSmqProcess();
        startBtsProcess();
        m_btnReboot->Enable(true);
    }
    else if (evt.GetEventObject() == m_btnOK)
    {
        apply();
        Close();
    }
    else if (evt.GetEventObject() == m_btnMail)
    {
        setMail();
    }
    else if (evt.GetEventObject() == m_btnCancel)
    {
        Close();
    }
    else if (evt.GetEventObject() == m_btnApply)
    {
        apply();
    }
    else 
    {
        evt.Skip();
    }
}

// ---------------------------------------------------------------------------
// AdminDialog
// ---------------------------------------------------------------------------
BEGIN_EVENT_TABLE(AdminDialog, wxDialog)
    EVT_BUTTON(wxID_ANY, AdminDialog::OnButton)
END_EVENT_TABLE()

const std::string AdminDialog::KEY = "Admin.user";
AdminDialog::AdminDialog(wxWindow * parent)
    :wxDialog(parent, 
        wxID_ANY, wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
    wxBoxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *sizerHeader = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *sizerButtom = new wxBoxSizer(wxHORIZONTAL);
    wxString wxStrPwd(gConfig.getStr(KEY).c_str(), wxConvUTF8);
    wxStaticText * title = NULL;
    
    wxStrPwd.Trim();
    if (wxStrPwd.IsEmpty())
    {
        title = new wxStaticText(
            this, 
            wxID_STATIC, 
            _("Password not set, please input:"), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT);
        m_bSet = false;
    }
    else
    {
        title = new wxStaticText(
            this, 
            wxID_STATIC, 
            _("Please input Admin password:"), 
            wxDefaultPosition, 
            wxDefaultSize, 
            wxALIGN_LEFT);
        m_bSet = true;
    }
    sizerHeader->Add(
        title,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxALL,
        5);
    m_pTxtPwd = new wxTextCtrl(
        this, 
        wxID_ANY, wxT(""), 
        wxDefaultPosition, 
        wxDefaultSize, 
        wxTE_LEFT | wxTE_PASSWORD); 
    sizerHeader->Add(
        m_pTxtPwd,
        1,
        wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL,
        5);
    m_btnOK = new wxButton(this, wxID_ANY, _("OK"));
    m_btnCancel = new wxButton(this, wxID_ANY, _("Cancel"));
    sizerButtom->Add(m_btnOK, 0, wxALIGN_CENTER | wxALL, 5);
    sizerButtom->Add(m_btnCancel, 0, wxALIGN_CENTER | wxALL, 5);
    sizerTop->Add(sizerHeader, 1, wxALIGN_CENTER);
    sizerTop->Add(sizerButtom, 0, wxALIGN_CENTER);
    SetSizer(sizerTop);
    sizerTop->Fit(this);
    sizerTop->SetSizeHints(this);
}

void AdminDialog::OnButton(wxCommandEvent& evt)
{
    if (evt.GetEventObject() == m_btnOK)
    {
        wxString savedPwd(gConfig.getStr(KEY).c_str(), wxConvUTF8);
        if (m_bSet) 
        {
            if (m_pTxtPwd->GetValue().Cmp(savedPwd) == 0)
            {
                //TODO: let user know passwrod varification passed                
                EndModal(PWDOK);
            }
            else
            {
                evt.Skip();
            }
        }
        else
        {
            std::string strVal(m_pTxtPwd->GetValue().mb_str());
            gConfig.set(KEY, strVal);
            //TODO: let user know passwrod varification passed
            EndModal(PWDOK);
        }
        
    }
    else if (evt.GetEventObject() == m_btnCancel)
    {
        Close();
    }
    else 
    {
        evt.Skip();
    }
}
